package com.henry.base.concurrency.nio;

import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;
import java.util.Iterator;
import java.util.Set;

public class NioServer {


    private void start() {
        try {
            ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
            serverSocketChannel.configureBlocking(false);
            serverSocketChannel.bind(new InetSocketAddress(8000));

//            SelectorProvider provider = SelectorProvider.provider();
            Selector selector = Selector.open();
            serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
            for (; ; ) {
                selector.select();
                Set<SelectionKey> selectionKeys = selector.selectedKeys();
                Iterator<SelectionKey> iterator = selectionKeys.iterator();
                while (iterator.hasNext()) {
                    SelectionKey key = iterator.next();
                    iterator.remove();
                    if (key.isValid() && key.isAcceptable()) {
                        doAccept(key);
                    } else if (key.isValid() && key.isReadable()) {
                        doRead(key);
                    } else if (key.isValid() && key.isWritable()) {
                        doWrite(key);
                    }

                }
                System.out.println();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    private void doWrite(SelectionKey key) throws IOException{
        SocketChannel socketChannel = (SocketChannel) key.channel();
        ByteBuffer buffer = ByteBuffer.allocate(128);
        String eval=  key.attachment().toString();
        socketChannel.write(buffer.wrap(eval.getBytes()));
        socketChannel.register(key.selector(), SelectionKey.OP_READ);
//        key.cancel();
    }

    private void doRead(SelectionKey key) throws IOException{
        SocketChannel socketChannel = (SocketChannel) key.channel();
//        ByteBuffer buffer =(ByteBuffer) key.attachment();
        ByteBuffer buffer = ByteBuffer.allocate(128);
        int len = socketChannel.read(buffer);
        if (len < 0) {
            socketChannel.shutdownInput();
            socketChannel.shutdownOutput();
            socketChannel.close();
        }else {
            buffer.flip();
            String string = Charset.defaultCharset().decode(buffer).toString();
            System.out.println("收到客户端内容:"+string);
            ScriptEngineManager manager = new ScriptEngineManager();
            ScriptEngine js = manager.getEngineByName("js");
            Object eval;
            try {
                eval = js.eval(string);
                System.out.println(eval);
            } catch (ScriptException e) {
                e.printStackTrace();
                eval = "js expression error!";
            }
            socketChannel.register(key.selector(), SelectionKey.OP_WRITE, eval);
//                    new Charset new CharsetDecoder().decode(buffer).toString();
        }


    }

    private void doAccept(SelectionKey key) throws IOException {
        ServerSocketChannel channel = (ServerSocketChannel) key.channel();
        //在这里可以判断白名单
//        channel.
        SocketChannel socketChannel = channel.accept();
        SocketAddress localAddress = socketChannel.getLocalAddress();
        SocketAddress remoteAddress = socketChannel.getRemoteAddress();
        socketChannel.configureBlocking(false);
        socketChannel.register(key.selector(), SelectionKey.OP_READ,ByteBuffer.allocate(1024));
    }

    public static void main(String[] args) {
        new NioServer().start();
    }
}
